﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using Isuka.Iteration;

namespace Isuka.Spiritual
{
    partial class Rules<T, A>
    {
        internal static RuleResult<T> _True(IBidirectionalIterator<T> it)
        {
            Contract.Requires(it != null);

            return new RuleResult<T>(it, true);
        }

        internal static RuleResult<T> _False(IBidirectionalIterator<T> it)
        {
            Contract.Requires(it != null);

            return new RuleResult<T>(it, false);
        }

        internal static RuleResult<T> _Result(IBidirectionalIterator<T> it, bool result)
        {
            Contract.Requires(it != null);

            return new RuleResult<T>(it, result);
        }

        internal static RuleResult<T> _SeqEq<X>(IBidirectionalIterator<T> first
                                              , IBidirectionalIterator<T> last
                                              , X expected)
            where X : IEnumerable<T>
        {
            Contract.Requires(first != null);
            Contract.Requires(last != null);
            Contract.Requires(expected != null);

            var it = first.Copy();
            foreach (var item in expected)
            {
                if (it.Equals(last) || !it.Current.Equals(item))
                {
                    return _False(it);
                }
                it.MoveNext();
            }
            return _True(it);
        }


        internal static RuleFunc _Eq(T value)
        {
            Contract.Ensures(Contract.Result<RuleFunc>() != null);

            return (i, c, s) =>
            {
                i = s(i, c);
                if (!i.Equals(c.Last) && i.Current.Equals(value))
                {
                    i.MoveNext();
                    return _True(i);
                }
                else
                {
                    return _False(i);
                }
            };
        }

        internal static RuleFunc _Eq(IEnumerable<T> values)
        {
            Contract.Ensures(Contract.Result<RuleFunc>() != null);

            return (i, c, s) =>
            {
                i = s(i, c);
                foreach (var v in values)
                {
                    if (!i.Equals(c.Last) && i.Current.Equals(v))
                    {
                        i.MoveNext();
                    }
                    else
                    {
                        return _False(i);
                    }
                }
                return _True(i);
            };
        }

    }
}
